package com.ruoyi.swap.openapi.price.controller;

import java.sql.Timestamp;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import javax.servlet.http.HttpServletResponse;

import com.ruoyi.swap.constants.SwapMonitorConstants;
import com.ruoyi.swap.openapi.price.domain.SwapOpenapiPrice;
import com.ruoyi.swap.openapi.price.domain.SwapOpenapiPrice;
import com.ruoyi.swap.openapi.price.domain.VO.SwapOpenapiPriceVO;
import com.ruoyi.swap.openapi.price.domain.VO.SwapOpenapiPriceVO;
import com.ruoyi.swap.openapi.price.service.ISwapOpenapiPriceService;
import com.ruoyi.util.LarkDangerRobotUtils;
import com.ruoyi.util.LarkRecoverRobotUtils;
import com.ruoyi.util.WebSocketUtilsReq;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;


/**
 * 指数_标记价格Controller
 *
 * @author saumell
 * @date 2024-08-19
 */
@RestController
@RequestMapping("/sw_api_price/sw_api_price_bak")
public class SwapOpenapiPriceController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(SwapOpenapiPriceController.class);

    @Autowired
    private ISwapOpenapiPriceService swapOpenapiPriceService;

    @Value("${my.lark.dangerlark}")
    private String dangerlark;

    @Value("${my.lark.recoverlark}")
    private String recoverlark;

    /**
     * 查询指数_标记价格列表
     */
    @PreAuthorize("@ss.hasPermi('sw_api_price:sw_api_price_bak:list')")
    @GetMapping("/list")
    public TableDataInfo list(SwapOpenapiPriceVO swapOpenapiPrice) {
        startPage();
        List<SwapOpenapiPriceVO> list = swapOpenapiPriceService.selectSwapOpenapiPriceList(swapOpenapiPrice);
        return getDataTable(list);
    }

    /**
     * 导出指数_标记价格列表
     */
    @PreAuthorize("@ss.hasPermi('sw_api_price:sw_api_price_bak:export')")
    @Log(title = "指数_标记价格", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SwapOpenapiPriceVO swapOpenapiPrice) {
        List<SwapOpenapiPriceVO> list = swapOpenapiPriceService.selectSwapOpenapiPriceList(swapOpenapiPrice);
        ExcelUtil<SwapOpenapiPriceVO> util = new ExcelUtil<SwapOpenapiPriceVO>(SwapOpenapiPriceVO.class);
        util.exportExcel(response, list, "指数_标记价格数据");
    }

    private static String checkoutmessage(String message) {
        try {
            JSONObject jsonObject = JSON.parseObject(message);
            StringBuilder errors = new StringBuilder();

            // 0. 检查是否为空 JSON 对象
            if (jsonObject.isEmpty()) {
                return "false, Server未推送指数_标记价格数据";
            }

            // 必需字段列表
            String[] requiredFields = {"currentFundRate", "indexPrice", "tagPrice", "nextFundRate"};

            // 1. 检查每个必需字段是否存在并且值有效且不为0
            for (String field : requiredFields) {
                if (!jsonObject.containsKey(field)) {
                    errors.append("缺失字段：").append(field).append("；");
                } else {
                    double value = jsonObject.getDoubleValue(field);
                    if (Double.isNaN(value) || Double.isInfinite(value) || value == 0) {
                        errors.append("字段值无效：").append(field).append("；");
                    }
                }
            }

            // 2. 返回错误信息
            if (errors.length() > 0) {
                return "false, " + errors.toString().trim().replaceAll("；$", "；");
            }

            return "true";
        } catch (Exception e) {
            return "false, JSON解析错误: " + e.getMessage();
        }
    }

    /**
     * 通过OpenAPI调用合约price
     */

    public void swapOpenapiPrice() {
        List<SwapOpenapiPriceVO> swapOpenAPIList = swapOpenapiPriceService.selectSwapAllData();
//      新建放置需要报警、故障修复交易对的id
        List<Integer> dangerProductionInspections = new ArrayList<Integer>();
        List<Integer> recoverProductionInspections = new ArrayList<Integer>();
        for (SwapOpenapiPriceVO swapOpenapiPriceVO : swapOpenAPIList) {
            Integer id = swapOpenapiPriceVO.getId();
            String currencyPair = swapOpenapiPriceVO.getCurrencyPair();
            String callingState = swapOpenapiPriceVO.getCallingState();
            Date lastExecutionTime = swapOpenapiPriceVO.getLastExecutionTime();
            Integer successTimes = swapOpenapiPriceVO.getSuccessTimes();
            Integer failTimes = swapOpenapiPriceVO.getFailTimes();
            Integer dangerWarning = swapOpenapiPriceVO.getDangerWarning();
            Integer safeWarning = swapOpenapiPriceVO.getSafeWarning();
            String openapirequest = null;
            WebSocketUtilsReq webSocketUtilsReq = null;
            OkHttpClient client = new OkHttpClient().newBuilder().build();
            try {
                Request request = new Request.Builder()
                        .url(MessageFormat.format(SwapMonitorConstants.SWAP_OPENAPI_PRICE, currencyPair))
                        .get()
                        .build();
                Response response = client.newCall(request).execute();
                String responseBody = response.body().string();
//校验
                log.info(responseBody);
                openapirequest = checkoutmessage(responseBody);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 处理返回的响应
            if (openapirequest == null || openapirequest.isEmpty()) {
//              合约-price-api-未接收到数据
                if (Objects.isNull(callingState) || callingState.isEmpty()) {
                    //数据库中没有数据，说明是第一次订阅即失败
                    //将调用失败的id放入dangerProductionInspections中
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    successTimes = 0;
                    failTimes = 1;
                    Integer currencysId = swapOpenapiPriceService.queryCurryNumber(currencyPair);
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, currencysId, "off_line", lastExecutionTime, successTimes, failTimes, "Server未推送Kline数据", null, null, null);
                    swapOpenapiPriceService.insertSwapOpenapiPrice(o1);
                    dangerProductionInspections.add(o1.getId());
                    log.info("[合约-OpenaAPI-指数_标记价格-1}：【" + currencyPair + "】首次调用即失败");
                } else if (callingState.equals("off_line")) {
                    //订阅一直失败
                    //将调用失败的id放入dangerProductionInspections中
                    if (dangerWarning == null || dangerWarning == 1) {
                        dangerProductionInspections.add(id);
                    }
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    failTimes = failTimes + 1;
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, null, callingState, lastExecutionTime, successTimes, failTimes, "Server未推送Kline数据", null, null, null);
                    swapOpenapiPriceService.updateSwapOpenapiPrice(o1);
                    log.info("[合约-OpenaAPI-指数_标记价格-2}：【" + currencyPair + "】订阅一直失败");
                } else if (callingState.equals("on_line")) {
                    //此种情况为第一次订阅失败
                    //将调用失败的id放入dangerProductionInspections中
                    dangerProductionInspections.add(id);
                    callingState = "off_line";
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    failTimes = failTimes + 1;
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, null, callingState, lastExecutionTime, successTimes, failTimes, "Server未推送Kline数据", null, null, null);
                    swapOpenapiPriceService.updateSwapOpenapiPrice(o1);
                    log.info("[合约-OpenaAPI-指数_标记价格-3}：【" + currencyPair + "】订阅首次失败");
                } else {
                    log.info("+++++++++++++++++++++++++++订阅失败未知情况+++++++++++++++++++++++++++++++");
                    log.info("[合约-OpenaAPI-指数_标记价格-4}：【" + currencyPair + "】未知情况");
                }
            } else if (openapirequest != null && openapirequest != null && openapirequest.startsWith("false")) {
//              处理返回值包含 "false" 的情况
                if (Objects.isNull(callingState) || callingState.isEmpty()) {
                    //数据库中没有数据，说明是第一次订阅即失败
                    //将调用失败的id放入dangerProductionInspections中
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    successTimes = 0;
                    failTimes = 1;
                    Integer currencysId = swapOpenapiPriceService.queryCurryNumber(currencyPair);
                    String s = openapirequest;
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, currencysId, "off_line", lastExecutionTime, successTimes, failTimes, openapirequest.split(",")[1], null, null, null);
                    swapOpenapiPriceService.insertSwapOpenapiPrice(o1);
                    dangerProductionInspections.add(o1.getId());
                    log.info("[合约-OpenaAPI-指数_标记价格-5}：【" + currencyPair + "】" + openapirequest);
                } else if (callingState.equals("off_line")) {
                    //订阅一直失败
                    //将调用失败的id放入dangerProductionInspections中
                    if (dangerWarning == null || dangerWarning == 1) {
                        dangerProductionInspections.add(id);
                    }
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    failTimes = failTimes + 1;
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, null, callingState, lastExecutionTime, successTimes, failTimes, openapirequest.split(",")[1], null, null, null);
                    swapOpenapiPriceService.updateSwapOpenapiPrice(o1);
                    log.info("[合约-OpenaAPI-指数_标记价格-6}：【" + currencyPair + "】" + openapirequest);
                } else if (callingState.equals("on_line")) {
                    //此种情况为第一次订阅失败
                    //将调用失败的id放入dangerProductionInspections中
                    dangerProductionInspections.add(id);
                    callingState = "off_line";
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    failTimes = failTimes + 1;
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, null, callingState, lastExecutionTime, successTimes, failTimes, openapirequest.split(",")[1], null, null, null);
                    swapOpenapiPriceService.updateSwapOpenapiPrice(o1);
                    log.info("[合约-OpenaAPI-指数_标记价格-7}：【" + currencyPair + "】" + openapirequest);
                } else {
                    log.info("+++++++++++++++++++++++++++订阅失败未知情况+++++++++++++++++++++++++++++++");
                    log.info("[合约-OpenaAPI-指数_标记价格-8}：【" + currencyPair + "】" + openapirequest);
                }
            } else if (openapirequest != null && openapirequest != null && openapirequest.equals("true")) {
//              订阅+格式校验均成功！
                if (Objects.isNull(callingState) || callingState.isEmpty()) {
//    首次订阅
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    successTimes = 1;
                    failTimes = 0;
                    Integer currencysId = swapOpenapiPriceService.queryCurryNumber(currencyPair);
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, currencysId, "on_line", lastExecutionTime, successTimes, failTimes, null, null, null, null);
                    swapOpenapiPriceService.insertSwapOpenapiPrice(o1);
                    log.info("[合约-OpenaAPI-指数_标记价格-9}：【" + currencyPair + "】" + openapirequest);
                } else if (callingState.equals("on_line")) {
                    //订阅一直成功
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    successTimes = successTimes + 1;
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, null, callingState, lastExecutionTime, successTimes, failTimes, null, null, null, null);
                    swapOpenapiPriceService.updateSwapOpenapiPrice(o1);
                    log.info("[合约-OpenaAPI-指数_标记价格-10}：【" + currencyPair + "】" + openapirequest);
                } else if (callingState.equals("off_line")) {
                    //订阅故障修复，复通
                    if (safeWarning == null || safeWarning == 1) {
                        recoverProductionInspections.add(id);
                    }
                    callingState = "on_line";
                    LocalDateTime currentDateTime = LocalDateTime.now();
                    lastExecutionTime = Timestamp.valueOf(currentDateTime);
                    successTimes = successTimes + 1;
                    SwapOpenapiPrice o1 = new SwapOpenapiPrice(id, null, callingState, lastExecutionTime, successTimes, failTimes, null, null, null, null);
                    swapOpenapiPriceService.updateSwapOpenapiPrice(o1);
                    log.info("[合约-OpenaAPI-指数_标记价格-11}：【" + currencyPair + "】" + openapirequest);
                } else {
                    log.info("+++++++++++++++++++++++++++订阅成功未知情况+++++++++++++++++++++++++++++++");
                    log.info("[合约-OpenaAPI-指数_标记价格-12}：【" + currencyPair + "】" + openapirequest);
                }
            }
        }
        List<SwapOpenapiPriceVO> swapKlineCurrencysList_new = swapOpenapiPriceService.selectSwapAllData();
//dangerProductionInspections :断开交易对对应id
//recoverProductionInspections  ：复通交易对对应id
//需要发送危险报警对象
        List<SwapOpenapiPriceVO> allProductionInspections2 = new ArrayList<>();
//需要发送复通信息对象
        List<SwapOpenapiPriceVO> allProductionInspections3 = new ArrayList<>();
        for (int i = 0; i < swapKlineCurrencysList_new.size(); i++) {
            Integer id = swapKlineCurrencysList_new.get(i).getId();
            if (dangerProductionInspections.contains(id)) {
                allProductionInspections2.add(swapKlineCurrencysList_new.get(i));
            } else if (recoverProductionInspections.contains(id)) {
                allProductionInspections3.add(swapKlineCurrencysList_new.get(i));
            }
        }

        if (!allProductionInspections2.isEmpty()) {
            if (allProductionInspections2.size() == 1) {
// 如果只有一条数据
                String name = allProductionInspections2.get(0).getCurrencyPair();
                Date time = allProductionInspections2.get(0).getLastExecutionTime();
                String reason = allProductionInspections2.get(0).getLastFailureReason();
                String formattedDate = "";
                if (time != null) {
                    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    formattedDate = formatter.format(time);
                }
// 拼接调用失败报警信息...
                String DangerLarkNotice = "【合约-指数_标记价格-OpenaAPI】下方为订单簿故障的交易对名称及调用时间，请您关注！\n";
                DangerLarkNotice += "交易对名称： " + name + "   " + "故障时间： " + formattedDate + "    故障原因： " + reason + "   " + "\n";
                String dangernotice = LarkDangerRobotUtils.notice(DangerLarkNotice, dangerlark);
// 更新数据库状态
                Integer id = allProductionInspections2.get(0).getId();
                String statusMessage = dangernotice.equals("lark_success") ? "Lark发送故障X信息情况成功！" : "Lark发送故障X信息情况失败！";
                SwapOpenapiPrice o2 = new SwapOpenapiPrice(id, null, null, null, null, null, null, dangernotice.equals("lark_success") ? 0 : 1, null, statusMessage);
                swapOpenapiPriceService.updateSwapOpenapiPrice(o2);
//}
            } else {
// 如果有多条数据，正常调用notice
                String DangerLarkNotice = "【合约-指数_标记价格-OpenaAPI】下方为订单簿故障的交易对名称及调用时间，请您关注！\n";
                boolean needNotice = false; // 是否需要发送通知
                for (int i = 0; i < allProductionInspections2.size(); i++) {
                    String name = allProductionInspections2.get(i).getCurrencyPair();
                    Date time = allProductionInspections2.get(i).getLastExecutionTime();
                    String reason = allProductionInspections2.get(i).getLastFailureReason();
                    String formattedDate = "";
                    if (time != null) {
                        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        formattedDate = formatter.format(time);
                    }
                    DangerLarkNotice += "交易对名称： " + name + "   " + "故障时间： " + formattedDate + "    故障原因： " + reason + "   " + "\n";
                }
                String dangernotice = LarkDangerRobotUtils.notice(DangerLarkNotice, dangerlark);
// 检查通知是否成功发送
                if (dangernotice.equals("lark_success")) {
                    // 更新数据库状态
                    for (int i = 0; i < allProductionInspections2.size(); i++) {
                        Integer id = allProductionInspections2.get(i).getId();
                        String statusMessage = "Lark发送故障X信息情况成功！";
                        SwapOpenapiPrice o2 = new SwapOpenapiPrice(id, null, null, null, null, null, null, 0, null, statusMessage);
                        swapOpenapiPriceService.updateSwapOpenapiPrice(o2);
                    }
                } else {
                    // 更新数据库状态
                    for (int i = 0; i < allProductionInspections2.size(); i++) {
                        Integer id = allProductionInspections2.get(i).getId();
                        String statusMessage = "Lark发送故障X信息情况失败！";
                        SwapOpenapiPrice o2 = new SwapOpenapiPrice(id, null, null, null, null, null, null, 1, null, statusMessage);
                        swapOpenapiPriceService.updateSwapOpenapiPrice(o2);
                    }
                }
            }
        }

        if (allProductionInspections3.size() != 0) {
//    拼接重新调用成功对象
            String RecoverLarkNotice = "";
            RecoverLarkNotice += "【合约-指数_标记价格-OpenaAPI】下方为K恢复的交易对名称及调用时间，请您关注！" + "\n";
            for (int i = 0; i < allProductionInspections3.size(); i++) {
                String name = allProductionInspections3.get(i).getCurrencyPair();
                Date time = allProductionInspections3.get(i).getLastExecutionTime();
                String formattedDate = "";
                if (time != null) {
                    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    formattedDate = formatter.format(time);
                }
                RecoverLarkNotice += "交易对名称： " + name + "   " + "恢复时间： " + formattedDate + "   " + "\n";
            }
            String recovernotice = LarkRecoverRobotUtils.notice(RecoverLarkNotice, recoverlark);
            for (int i = 0; i < allProductionInspections3.size(); i++) {
//判断复通信息通知情况
                if (recovernotice.equals("lark_fail")) {
//    通知失败
                    for (int j = 0; j < allProductionInspections3.size(); j++) {
                        Integer id = allProductionInspections3.get(j).getId();
                        SwapOpenapiPrice o2 = new SwapOpenapiPrice(id, null, null, null, null, null, null, null, 1, "Lark发送故障V信息情况失败！");
                        swapOpenapiPriceService.updateSwapOpenapiPrice(o2);
                    }
                } else {
//    通知成功
                    for (int k = 0; k < allProductionInspections3.size(); k++) {
                        Integer id = allProductionInspections3.get(k).getId();
                        SwapOpenapiPrice o2 = new SwapOpenapiPrice(id, null, null, null, null, null, null, null, 0, "Lark发送故障V信息情况失败！");
                        swapOpenapiPriceService.updateSwapOpenapiPrice(o2);
                    }
                }
            }
        }
        log.info("============【【合约-指数_标记价格-OpenaAPI】执行完成============");
    }

}
